package com.jsb.laundry.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.jsb.laundry.common.enums.BusinessType;
import com.jsb.laundry.common.enums.Lottery;
import com.jsb.laundry.common.enums.ReturnStatusCode;
import com.jsb.laundry.common.response.WebResponse;
import com.jsb.laundry.common.utils.JSBUtil;
import com.jsb.laundry.model.dto.CapitalAccountUnstLogListRequest;
import com.jsb.laundry.model.vo.*;
import com.jsb.laundry.service.CapitalAccountServiceImpl;
import com.jsb.laundry.service.UserLotteryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Api(tags = {"用户抽奖"})
@RestController
@RequestMapping("/userLottery/")
public class UserLotteryController {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserLotteryController.class);

    @Resource
    private UserLotteryService userLotteryService;
    @Resource
    private CapitalAccountServiceImpl capitalAccountService;

    @ApiOperation(value = "用户抽奖分享朋友圈", notes = "用户抽奖分享朋友圈", httpMethod = "POST")
    @PostMapping("userLotterySharingMoments")
    public WebResponse userLotterySharingMoments(@RequestBody JSONObject object) {
        String userId = object.getString("userId");
        if (JSBUtil.isEmptyString(userId)) {
            return WebResponse.success(ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getCode(), ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getMsg());
        }
        String today = JSBUtil.newDate(0);//当天时间
        int count = userLotteryService.findByLotteryUserCount(userId, today, today);
        if (count == 1) {//邀请次数上线
            return WebResponse.success(ReturnStatusCode.INVITATION_TIMES_ONLINE.getCode(), ReturnStatusCode.INVITATION_TIMES_ONLINE.getMsg());
        }
        userLotteryService.addLotteryUser(userId, Lottery.shareMoments.getNum());
        int lotteryNum = userLotteryService.updUserLotteryNum(userId, Lottery.shareMoments.getNum());//抽奖邀请人加次数
        if (lotteryNum == 0) {
            LOGGER.info("UserLotteryController:userLotterySharingMoments, updUserLotteryNum is 0, userId:{},today{}", userId, today);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

        }
        int addUserLotteryRecordRoad = userLotteryService.addUserLotteryRecordRoad(userId, Lottery.shareMoments.getMsg(), Lottery.shareMoments.getCode(), Lottery.shareMoments.getNum());//抽奖获得次数途径

        return WebResponse.successData(addUserLotteryRecordRoad);
    }

    @ApiOperation(value = "用户抽奖获奖列表", notes = "用户抽奖获奖列表", httpMethod = "POST")
    @PostMapping("userLuckyDrawAwardList")
    public WebResponse userLuckyDrawAwardList() {
        List<UserLuckDrawAwardListVo> userLuckDrawAwardListVos = userLotteryService.userLuckyDrawAwardList();
        for (UserLuckDrawAwardListVo userLuckDrawAwardListVo : userLuckDrawAwardListVos) {
            String userPhone = userLuckDrawAwardListVo.getUserPhone();
            userLuckDrawAwardListVo.setUserPhone(JSBUtil.maskPhoneNumber(userPhone));

        }
        return WebResponse.successData(userLuckDrawAwardListVos);
    }

    @ApiOperation(value = "用户抽奖获奖计数", notes = "用户抽奖获奖计数", httpMethod = "POST")
    @PostMapping("userLuckyDrawAwardCount")
    public WebResponse userLuckyDrawAwardCount(@RequestBody JSONObject object) {
        String userId = object.getString("userId");
        if (JSBUtil.isEmptyString(userId)) {
            return WebResponse.success(ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getCode(), ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getMsg());
        }
        UserLuckyDrawAwardCountVo userLuckyDrawAwardCountVo = userLotteryService.userLuckyDrawAwardCount(userId);
        //判断用户是否有抽奖次数
        UserLotteryListVO lottery = userLotteryService.findByUserLotteryNum(userId);
        if (JSBUtil.isEmptyObject(lottery)) {
            return WebResponse.success(ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getCode(), ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getMsg());
        }
        userLuckyDrawAwardCountVo.setUserCount(String.valueOf(lottery.getNum()));
        return WebResponse.successData(userLuckyDrawAwardCountVo);
    }

    @ApiOperation(value = "用户抽奖次数", notes = "用户抽奖次数", httpMethod = "POST")
    @PostMapping("numBerLotteryDraws")
    public WebResponse numBerLotteryDraws(@RequestBody JSONObject object) {
        String userId = object.getString("userId");
        if (JSBUtil.isEmptyString(userId)) {
            return WebResponse.success(ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getCode(), ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getMsg());
        }
        int num = userLotteryService.numBerLotteryDraws(userId);
        return WebResponse.successData(num);
    }

    @ApiOperation(value = "抽奖列表", notes = "抽奖列表", httpMethod = "POST")
    @PostMapping("list")
    public WebResponse list() {
        List<UserLotteryPrizeListVo> list = userLotteryService.list();
        return WebResponse.successData(list);
    }

    @ApiOperation(value = "开始抽奖", notes = "开始抽奖", httpMethod = "POST")
    @PostMapping("startDraw")
    @Transactional
    public synchronized WebResponse startDraw(@RequestBody JSONObject object) {
        String userId = object.getString("userId");
        if (JSBUtil.isEmptyString(userId)) {
            return WebResponse.success(ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getCode(), ReturnStatusCode.PLEASE_ENTER_THE_NECESSARY_PARAMETERS.getMsg());
        }

        //判断用户是否有抽奖次数
        UserLotteryListVO lotteryNumber = userLotteryService.findByUserLotteryNum(userId);
        if (lotteryNumber.getNum() == 0) {
            return WebResponse.success(ReturnStatusCode.INSUFFICIENT_NUMBER_OF_LOTTERY_DRAWS.getCode(), ReturnStatusCode.INSUFFICIENT_NUMBER_OF_LOTTERY_DRAWS.getMsg());
        }

        //抽奖列表
        List<UserLotteryPrizeListVo> list = userLotteryService.list();

        //判断抽奖池是否还有奖品
        if ("1".equals(lotteryNumber.getWhite())) {//白名单看白名单用户的剩余奖励数量
            list = list.stream()
                    .filter(vo -> vo.getWhitePrizeWinningRate() != 0)
                    .filter(vo -> vo.getPrizeNum() != 0)
                    .collect(Collectors.toList());
        } else {//普通用户看普通用户的剩余奖励数量
            list = list.stream()
                    .filter(vo -> vo.getPrizeWinningRate() != 0)
                    .filter(vo -> vo.getPrizeNum() != 0)
                    .collect(Collectors.toList());
        }

        List<Integer> collect = list.stream().map(UserLotteryPrizeListVo::getPrizeNum).collect(Collectors.toList());
        int totalRemainingNum = collect.stream().mapToInt(Integer::intValue).sum();
        if (totalRemainingNum == 0) {
            return WebResponse.success(ReturnStatusCode.THE_PRIZE_IS_NO_LONGER_AVAILABLE.getCode(), ReturnStatusCode.THE_PRIZE_IS_NO_LONGER_AVAILABLE.getMsg());
        }
        String id = "";
        String orderId = "cj" + JSBUtil.generateLongOrderId();//抽奖流水号
        //判断该用户是否是白名单
        if ("1".equals(lotteryNumber.getWhite())) {//白名单
            //白名单中奖率
            id = generateRandomReward("1", list);

            //减去奖品表数量
            userLotteryService.updatePrizeNumSub(1, id);
            //减去抽奖次数
            userLotteryService.updateNumberSub(1, userId);
            //添加到抽奖记录表
            userLotteryService.addLotteryRecords(id, userId, orderId);
            //查询改奖品多少钱入已结算
            int byPrizeMoney = userLotteryService.findByPrizeMoney(id);

            //结算
            int settlement = capitalAccountService.lotteryAwardSettlement(byPrizeMoney, userId, orderId);
            if (settlement == 0) {
                LOGGER.info("抽奖奖励失败");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
        } else {
            //普通用户抽奖
            id = generateRandomReward("0", list);
            if ("0".equals(id)) {
                return WebResponse.success(ReturnStatusCode.THE_PRIZE_IS_NO_LONGER_AVAILABLE.getCode(), ReturnStatusCode.THE_PRIZE_IS_NO_LONGER_AVAILABLE.getMsg());
            }
            //减去奖品表数量
            userLotteryService.updatePrizeNumSub(1, id);
            //减去抽奖次数
            userLotteryService.updateNumberSub(1, userId);
            //添加到抽奖记录表
            userLotteryService.addLotteryRecords(id, userId, orderId);
            //查询改奖品多少钱入已结算
            int byPrizeMoney = userLotteryService.findByPrizeMoney(id);
            //结算
            int settlement = capitalAccountService.lotteryAwardSettlement(byPrizeMoney, userId, orderId);
            if (settlement == 0) {
                LOGGER.info("抽奖奖励失败");
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
        }
        return WebResponse.successData(id);
    }

    public static String generateRandomReward(String white, List<UserLotteryPrizeListVo> list) {
        List<String> idList = list.stream().map(UserLotteryPrizeListVo::getId).collect(Collectors.toList());//抽奖id
        List<Integer> numberList = list.stream().map(UserLotteryPrizeListVo::getPrizeNum).collect(Collectors.toList());//抽奖剩余数量
        List<Double> probabilities = new ArrayList<>();//抽奖率
        if ("0".equals(white)) { //普通用户中奖概率
            probabilities = list.stream().map(UserLotteryPrizeListVo::getPrizeWinningRate).collect(Collectors.toList());

        } else { //白名单用户中奖概率
            probabilities = list.stream().map(UserLotteryPrizeListVo::getWhitePrizeWinningRate).collect(Collectors.toList());

        }


        // 计算总概率
        double totalProbability = probabilities.stream().mapToDouble(Double::doubleValue).sum();

        // 生成随机数
        double random = Math.random() * totalProbability;

        // 根据随机数和概率进行抽奖 如果这个奖品数量没有了就继续根据抽奖率抽奖下一个商品 返回一个商品id  如果商品都没有了返回一个空

        //判断所有奖品为0返回一个null
        int totalRemainingNum = numberList.stream().mapToInt(Integer::intValue).sum();
        if (totalRemainingNum == 0) {
            return "0";
        }
        // 初始化奖品索引
        int prizeIndex = -1;
        // 遍历概率列表
        for (int i = 0; i < probabilities.size(); i++) {
            // 减去当前奖品的概率
            random -= probabilities.get(i);
            if (random <= 0) {
                prizeIndex = i;
                break;
            }
        }

        if (prizeIndex != -1) { // 存在中奖商品
            String prizeId = idList.get(prizeIndex); // 获取中奖商品的id
            int prizeNum = numberList.get(prizeIndex); // 获取中奖商品的剩余数量
            if (prizeNum > 0) { // 如果中奖商品还有剩余数量
                // 更新中奖商品的剩余数量
                numberList.set(prizeIndex, prizeNum - 1);
                return prizeId;
            } else {

                // 中奖商品已经没有剩余数量了，继续抽下一个商品
                return generateRandomReward(white, list);
            }
        } else {
            // 所有商品都已经抽完
            throw new RuntimeException("所有商品都已抽完，没有中奖商品");
        }

    }

    @ApiOperation(value = "已结算列表", notes = "已结算列表", httpMethod = "POST")
    @PostMapping("capitalAccountLogList")
    public WebResponse capitalAccountLogList(@RequestBody CapitalAccountUnstLogListRequest capitalAccountUnstLogListRequest) {
        PageHelper.startPage(capitalAccountUnstLogListRequest.getPageNum(), capitalAccountUnstLogListRequest.getPageSize());
        List<CapitalAccountUnstLogListVo> capitalAccountUnstLogListVos = userLotteryService.capitalAccountLogList(capitalAccountUnstLogListRequest.getUserId());
        for (CapitalAccountUnstLogListVo capitalAccountUnstLogListVo : capitalAccountUnstLogListVos) {
            if (JSBUtil.isEmptyObject(capitalAccountUnstLogListVo)) {
                return WebResponse.successData(null);
            }
            if ("in".equals(capitalAccountUnstLogListVo.getType())) {
                capitalAccountUnstLogListVo.setType("+");
            } else if ("out".equals(capitalAccountUnstLogListVo.getType())) {
                capitalAccountUnstLogListVo.setType("-");
            }
            capitalAccountUnstLogListVo.setBusinessType("抽奖奖励");
            capitalAccountUnstLogListVo.setAmount(JSBUtil.turnDoubleStrNew(Double.parseDouble(capitalAccountUnstLogListVo.getAmount())));
        }
        return WebResponse.successData(capitalAccountUnstLogListVos);
    }
    @ApiOperation(value = "活动规则", notes = "活动规则", httpMethod = "POST")
    @PostMapping("rule")
    public WebResponse rule() {
        List<FindByRuleVo>  content =  userLotteryService.findByRule();
      return WebResponse.successData(content);
    }
}
